home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
3D Images
/
3D Images.iso
/
programs
/
amiga
/
rayshade
/
libshade
/
picture.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-12
|
8KB
|
355 lines
/*
* picture.c
*
* Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
* picture.c,v 4.1 1994/08/09 08:04:43 explorer Exp
*
* picture.c,v
* Revision 4.1 1994/08/09 08:04:43 explorer
* Bump version to 4.1
*
* Revision 1.1.1.1 1994/08/08 04:52:17 explorer
* Initial import. This is a prerelease of 4.0.6enh3, or 4.1 possibly.
*
* Revision 4.0.1.2 92/02/07 09:22:20 cek
* patch6: Fixed typo in MTV error message.
*
* Revision 4.0.1.1 92/01/10 16:28:28 cek
* patch3: Added check for nonexistent patial image file.
* patch3: Fixed declaration of nrow in count_rle_rows().
* patch3: Changed level of several error messages.
*
* Revision 4.0 91/07/17 14:47:00 kolb
* Initial version.
*
*/
#include "rayshade.h"
#include "picture.h"
#include "viewing.h"
#include "options.h"
#include "stats.h"
#include "zbuf.h"
#ifdef URT
unsigned char **outptr; /* Output buffer */
static int count_rle_rows();
#endif
/*
* Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
* correction.
*/
unsigned char
correct(x)
Float x;
{
/*
* Truncate values < 0 or > 1.
*/
if (x < 0)
return 0;
if (x > 1.)
return 255;
return (unsigned char)(x * 255.);
}
#ifdef URT
/*
* Open image file and write RLE header.
*/
void
PictureStart(argv)
char **argv;
{
char gammacom[40];
if (Options.framenum != Options.startframe) {
/*
* We've been here before;
* write a new header and return.
*/
rle_put_setup(&rle_dflt_hdr);
return;
}
/*
* If Appending, then we know that outfile is valid, 'cause
* we've already read its header.
*/
if (Options.appending) {
Options.pictfile = fopen(Options.imgname, "a");
if (Options.pictfile == (FILE *)0)
RLerror(RL_PANIC, "Cannot append to %s?!\n",
Options.imgname);
rle_dflt_hdr.rle_file = Options.pictfile;
rle_put_init(&rle_dflt_hdr);
/*
* Append "linefeed" to last line in outfile.
*/
if (Screen.miny > rle_dflt_hdr.ymin)
rle_skiprow(&rle_dflt_hdr, 1);
} else {
/*
* Starting image from scatch.
*/
if (Options.imgname) {
Options.pictfile = fopen(Options.imgname, "w");
if (Options.pictfile == (FILE *)NULL)
RLerror(RL_ABORT,"Cannot open %s for writing.",
Options.imgname);
} else
Options.pictfile = stdout;
rle_dflt_hdr.xmax = Screen.maxx;
rle_dflt_hdr.ymax = Screen.maxy;
rle_dflt_hdr.xmin = Screen.minx;
rle_dflt_hdr.ymin = Screen.miny;
rle_dflt_hdr.alpha = Options.alpha;
if (Options.alpha)
RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
if (Options.exp_output) {
RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
rle_dflt_hdr.ncolors = 4;
rle_putcom("exponential_data", &rle_dflt_hdr);
}
else
rle_dflt_hdr.ncolors = 3;
/*
* Document image gamma in RLE comment area.
* Options.gamma has been inverted.
*/
(void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
rle_putcom(gammacom, &rle_dflt_hdr);
/*
* Document command line in RLE history.
*/
rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
rle_dflt_hdr.rle_file = Options.pictfile;
rle_put_setup(&rle_dflt_hdr);
/*
* Flush the header. If we don't, and LINDA forks off
* a bunch of workers, strange things will happen (they'll
* all flush the buffer when they die, and you end up with
* lots of headers at the end of the file).
*/
(void)fflush(rle_dflt_hdr.rle_file);
}
if (Options.zbufprint) {
zbuffer.outfile = Options.imgname ?
strsave (Options.imgname) : NULL;
zbuffer.argv = argv;
}
if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
RLerror(RL_PANIC, "Unable to allocate image memory.\n");
}
/*
* Read RLE header to which we are appending in order determine
* old resolution, window location, and the like.
*/
void
PictureSetWindow()
{
if (Options.imgname == (char *)NULL)
RLerror(RL_ABORT,
"No partially-completed image file specified.\n");
/*
* Open image and read RLE header.
*/
Options.pictfile = fopen(Options.imgname, "r");
if (Options.pictfile == (FILE *)NULL) {
fprintf(stderr,
"Cannot open image file \"%s\". Creating new file.\n",
Options.imgname);
Options.appending = FALSE;
return;
}
rle_dflt_hdr.rle_file = Options.pictfile;
rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
/*
* If user specified a window that does not match what's in
* the header, complain.
if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
*/
/*
* Set window.
*/
Screen.minx = rle_dflt_hdr.xmin;
Screen.miny = rle_dflt_hdr.ymin;
Screen.maxx = rle_dflt_hdr.xmax;
Screen.maxy = rle_dflt_hdr.ymax;
/*
* Set alpha. Warn the user if the alpha option doesn't reflect
* what's already been rendered.
*/
if (Options.alpha != rle_dflt_hdr.alpha)
RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
Options.imgname,
rle_dflt_hdr.alpha ? "has" : "does not have");
Options.alpha = rle_dflt_hdr.alpha;
/*
* Determine number of scanlines written to file.
*/
Screen.miny += count_rle_rows(&rle_dflt_hdr);
if (Screen.miny > Screen.maxy) {
fprintf(stderr, "\"%s\" is a complete image.\n",
Options.imgname);
exit(0);
}
fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
Options.imgname, Screen.miny);
(void)fclose(Options.pictfile);
}
static int
count_rle_rows(hdr)
rle_hdr *hdr;
{
int y, ynext;
for (y = hdr->ymin - 1; (ynext = rle_getskip(hdr)) != 32768; y = ynext)
;
/*
* If we have not reached physical EOF, then we must be at logical EOF
* which means the image is complete regardless of the amount of
* scanline data present.
*/
if (!feof(hdr->rle_file))
y = hdr->ymax;
return y - hdr->ymin + 1;
}
/*
* Write a scanline of output.
* "buf" is an array of Color structures of size Screen.xsize. Each color
* component is normalized to [0, 1.].
*/
void
PictureWriteLine(buf)
Pixel *buf;
{
register int i, chan;
float floats[3];
rle_pixel pixels[4];
for(i = 0; i < Screen.xsize; i++) {
if (!Options.exp_output) {
/*
* Scale colors to fit unsigned char and check for
* over/underflow.
*/
outptr[0][i] = CORRECT(buf[i].r);
outptr[1][i] = CORRECT(buf[i].g);
outptr[2][i] = CORRECT(buf[i].b);
} else {
/*
* Convert 3 floats to 4 unsigned chars for
* 'exponential_data' RLE file.
*/
floats[0] = GAMMACORRECT(buf[i].r);
floats[1] = GAMMACORRECT(buf[i].g);
floats[2] = GAMMACORRECT(buf[i].b);
float_to_exp( 3, floats, pixels );
for (chan = 0; chan <= 3; chan++)
outptr[chan][i] = pixels[chan];
}
if (Options.alpha)
/*
* Don't gamma correct alpha channel.
*/
outptr[-1][i] = correct(buf[i].alpha);
}
rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
}
/*
* End the frame.
*/
void
PictureFrameEnd()
{
rle_puteof(&rle_dflt_hdr);
}
/*
* Close image file.
*/
void
PictureEnd()
{
(void)fclose(Options.pictfile);
}
#else /* !URT */
void
PictureStart(argv)
char **argv;
{
if (Options.imgname) {
Options.pictfile = fopen(Options.imgname, "w");
if (Options.pictfile == (FILE *)NULL)
RLerror(RL_ABORT, "Cannot open %s for writing.",
Options.imgname);
} else
Options.pictfile = stdout;
fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
(void)fflush(Options.pictfile);
}
void
PictureWriteLine(buf)
Pixel *buf;
{
register int i;
for (i = 0; i < Screen.xsize; i++) {
(void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
(void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
(void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
}
(void)fflush(Options.pictfile);
}
void
PictureFrameEnd()
{
/*
* Don't do anything -- generic format has no end-of-image marker.
*/
}
void
PictureEnd()
{
(void)fclose(Options.pictfile);
}
#endif /* URT */